package com.springboot.blog.controller;

import com.baomidou.kaptcha.Kaptcha;
import com.baomidou.kaptcha.exception.KaptchaException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.springboot.blog.dto.LayResponse;
import com.springboot.blog.entity.*;
import com.springboot.blog.entity.vo.ArticleVO;
import com.springboot.blog.entity.vo.NavVO;
import com.springboot.blog.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 文章表 前端控制器
 * </p>
 *
 * @author 4vsy
 * @since 2020-06-29
 */
@Controller
public class IndexController {
    @Autowired
    private IArticleService articleService;
    @Autowired
    private ICategoryService categoryService;
    @Autowired
    private Kaptcha kaptcha;
    @Autowired
    private ICommentService commentService;
    @Autowired
    private INavService navService;
    @Autowired
    private IBannerService bannerService;
    @Autowired
    private IArticleTagService articleTagService;
    @Autowired
    private ITagService tagService;
    @Autowired
    IBlogrollService blogrollService;

    @GetMapping("/")
    public String index(Model model) {
        setNavVOLit(model);//设置导航栏
        QueryWrapper<Article> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("browse", "id").last("limit 8");
        //点击排行八篇
        List<Article> hotArticles = articleService.list(queryWrapper);
        Article hotArticle = hotArticles.remove(0);
        //个人博客7片
        queryWrapper.clear();
        List<Article> blogArticles = articleService.list(queryWrapper.lambda().orderByDesc(Article::getHot, Article::getId).last("limit 7"));
        List<Article> blogArticlesLeft = Arrays.asList(blogArticles.remove(0), blogArticles.remove(0));

        //站长推荐八篇
        queryWrapper.clear();
        List<Article> recommendArticles = articleService.list(queryWrapper.lambda().orderByDesc(Article::getRecommend, Article::getId).last("limit 7"));
        Article recommendArticle = recommendArticles.remove(0);

        //查询两篇置顶文章
        queryWrapper.clear();
        List<Article> topArticles = articleService.list(queryWrapper.lambda().eq(Article::getTop, 1).orderByDesc(Article::getId).last("limit 2"));
        //查询8片最新文章
        queryWrapper.clear();
        List<Article> recentArticles = articleService.list(queryWrapper.lambda().orderByDesc(Article::getId).last("limit 8"));

        //查询首页左侧轮播图
        List<Banner> leftBanners = bannerService.list(new QueryWrapper<Banner>().lambda().eq(Banner::getType, "首页左侧"));
        List<Banner> rightBanners = bannerService.list(new QueryWrapper<Banner>().lambda().eq(Banner::getType, "首页右侧"));
        //查询友情链接
        List<Blogroll> blogrolls = blogrollService.list();

        model.addAttribute("hotArticles", hotArticles);
        model.addAttribute("hotArticle", hotArticle);
        model.addAttribute("blogArticlesLeft", blogArticlesLeft);
        model.addAttribute("blogArticles", blogArticles);
        model.addAttribute("topArticles", topArticles);
        model.addAttribute("recentArticles", recentArticles);
        model.addAttribute("recommendArticles", recommendArticles);
        model.addAttribute("recommendArticle", recommendArticle);
        model.addAttribute("categoryNames", getCategoryNames());
        model.addAttribute("leftBanners", leftBanners);
        model.addAttribute("rightBanners", rightBanners);
        model.addAttribute("blogrolls", blogrolls);
        return "index";
    }

    //使用自定义sql关联查询
    @GetMapping({"/article/{articleId}"})
    public String article(Model model, @PathVariable("articleId") Integer articleId) {
        setNavVOLit(model);//设置导航栏
        Article article = articleService.getById(articleId);
        //相关推荐6篇
        QueryWrapper<Article> queryWrapper = new QueryWrapper<>();
        List<Article> reArticles = articleService.list(queryWrapper.lambda().eq(Article::getCategoryId, article.getCategoryId()).last("limit 6"));
        //点击排行6篇
        queryWrapper.clear();
        List<Article> hotArticles = articleService.list(queryWrapper.orderByDesc("browse", "id").last("limit 6"));
        Article hotArticle = hotArticles.remove(0);

        //查询上一篇,下一篇
        queryWrapper.clear();
        Article articlePre = articleService.getOne(queryWrapper.lambda().lt(Article::getId, article.getId()).orderByDesc(Article::getId).last("limit 1"));
        queryWrapper.clear();
        Article articleEnd = articleService.getOne(queryWrapper.lambda().gt(Article::getId, article.getId()).last("limit 1"));
        ArticleVO articleVO = articleService.selectWithOther(articleId);
        //浏览量自增
        articleService.updateById(new Article()
                .setId(article.getId())
                .setBrowse(article.getBrowse() + 1));
        setHotTagList(model);//设置右侧热门tag
        model.addAttribute("article", articleVO);
        model.addAttribute("reArticles", reArticles);
        model.addAttribute("hotArticles", hotArticles);
        model.addAttribute("hotArticle", hotArticle);
        model.addAttribute("articlePre", articlePre);
        model.addAttribute("articleEnd", articleEnd);
        model.addAttribute("categoryNames", getCategoryNames());
        return "article";
    }
    //点赞文章
    @ResponseBody
    @PostMapping({"/article/{articleId}"})
    public LayResponse articleZan(@PathVariable("articleId") String articleId) {
        Article article = articleService.getById(articleId);
        article.setUp(article.getUp()+1);
        articleService.updateById(article);
        return new LayResponse().success("点赞成功");
    }

    @GetMapping({"/category/{categoryId}"})
    public String category(Model model, @PathVariable("categoryId") String categoryId) {
        return category(model, categoryId, 1);
    }

    @GetMapping("/category/{categoryId}/{pageNum}")
    public String category(Model model, @PathVariable("categoryId") String categoryId, @PathVariable("pageNum") int pageNum) {
        setNavVOLit(model);//设置导航栏
        Page<Article> page = new Page<>(pageNum, 10);
        Category category = categoryService.getById(categoryId);
        Page<Article> articlePage = articleService.page(page,new QueryWrapper<Article>().lambda().eq(Article::getCategoryId,categoryId));

        //站长推荐6篇
        List<Article> recommendArticles = articleService.list(new QueryWrapper<Article>().lambda().eq(Article::getCategoryId, categoryId).orderByDesc(Article::getRecommend, Article::getId).last("limit 6"));

        Article recommendArticle;
        if(recommendArticles.isEmpty()){
            recommendArticle=new Article();
        }else {
            recommendArticle = recommendArticles.remove(0);
        }
        setHotTagList(model);//设置右侧热门tag
        model.addAttribute("category", category);
        model.addAttribute("articlePage", articlePage);
        model.addAttribute("categoryNames", getCategoryNames());
        model.addAttribute("recommendArticles", recommendArticles);
        model.addAttribute("recommendArticle", recommendArticle);
        return "category";
    }

    private Map<Integer, String> getCategoryNames() {
        List<Category> list = categoryService.list(new QueryWrapper<Category>().lambda().select(Category::getId, Category::getTitle));
        Map<Integer, String> categoryNames = new HashMap<>();
        list.forEach(category -> {
            categoryNames.put(category.getId(), category.getTitle());
        });
        return categoryNames;
    }

    @GetMapping("/search")
    public String search(Model model, @RequestParam String keywords) {
        return search(model, keywords, 1);
    }

    @GetMapping("/search/{pageNum}")
    public String search(Model model, @RequestParam String keywords, @PathVariable("pageNum") int pageNum) {
        Page<Article> page = new Page<>(pageNum, 10);
        QueryWrapper<Article> articleQueryWrapper = new QueryWrapper<>();
        Page<Article> articlePage = articleService.page(page, articleQueryWrapper.lambda().like(Article::getTitle, keywords));
        model.addAttribute("title", keywords);
        model.addAttribute("type", "搜索");
        model.addAttribute("articlePage", articlePage);
        return commonPage(model);
    }

    @GetMapping("/tag/{tagName}")
    public String tag(Model model, @PathVariable("tagName") String tagName) {
        return tag(model,1,tagName);
    }

    @GetMapping("/tag/{pageNum}/{tagName}")
    public String tag(Model model, @PathVariable("pageNum") int pageNum, @PathVariable("tagName") String tagName) {
        Tag tag = tagService.getOne(new QueryWrapper<Tag>().lambda().eq(Tag::getName, tagName).select(Tag::getId));
        Page<ArticleTag> page = new Page<>(pageNum, 10);
        QueryWrapper<ArticleTag> articleQueryWrapper = new QueryWrapper<>();
        Page articleTag = articleTagService.page(page, articleQueryWrapper.lambda().eq(ArticleTag::getTagId, tag.getId()).select(ArticleTag::getArticleId));
        if(articleTag.getTotal()>0){
            List<ArticleTag> records = articleTag.getRecords();
            List<Integer> articleIds = records.stream()
                    .map(ArticleTag::getArticleId).collect(Collectors.toList());
            articleTag.setRecords(articleService.list(new QueryWrapper<Article>().lambda().in(Article::getId, articleIds)));
        }
        model.addAttribute("title", tagName);
        model.addAttribute("type", "标签");
        model.addAttribute("articlePage", articleTag);
        return commonPage(model);
    }

    private String commonPage(Model model){
        setNavVOLit(model);//设置导航栏
        QueryWrapper<Article> articleQueryWrapper = new QueryWrapper<>();
        //站长推荐6篇
        List<Article> recommendArticles = articleService.list(articleQueryWrapper.lambda().orderByDesc(Article::getRecommend, Article::getId).last("limit 6"));
        Article recommendArticle = recommendArticles.remove(0);
        model.addAttribute("categoryNames", getCategoryNames());
        model.addAttribute("recommendArticles", recommendArticles);
        model.addAttribute("recommendArticle", recommendArticle);
        return "commonPage";
    }

    //验证码 https://gitee.com/baomidou/kaptcha-spring-boot-starter
    @GetMapping("/kaptcha/render")
    @ResponseBody
    public void render() {
        kaptcha.render();
    }

    @PostMapping("/comment/add")
    @ResponseBody
    public Map commentAdd(@RequestParam Map<String, String> param, HttpServletRequest request) {
        HashMap<String, Object> map = new HashMap<>();
        try {
            kaptcha.validate(param.get("code"));
            map.put("code",200);
            map.put("msg","添加成功!");
            String ip = request.getHeader("x-forwarded-for");
            Comment comment = new Comment();
            comment.setArticleId(Integer.valueOf(param.get("id")));
            comment.setContent(param.get("comment"));
            comment.setUsername(param.get("username"));
            comment.setIp(ip);
            comment.setStatus(true);
            comment.setCreateTime(LocalDateTime.now());
            commentService.save(comment);
        } catch (KaptchaException exception) {
            map.put("code",500);
            map.put("msg","验证码错误!");
        }
        return map;
    }

    private void setNavVOLit(Model model){
        List<Nav> NavList = navService.list(new QueryWrapper<Nav>().lambda().eq(Nav::getPid, 0).eq(Nav::getStatus,true).orderByAsc(Nav::getSorts));
        List<NavVO> navVOLit = new ArrayList<>();
        for(Nav nav:NavList){
            List<Nav> list = navService.list(new QueryWrapper<Nav>().lambda().eq(Nav::getPid, nav.getId()).eq(Nav::getStatus,true).orderByAsc(Nav::getSorts));
            NavVO navVO=new NavVO();
            BeanUtils.copyProperties(nav,navVO);
            navVO.setChildren(list);
            navVOLit.add(navVO);
        }
        model.addAttribute("navVOLit", navVOLit);
    }
    private void setHotTagList(Model model){
        model.addAttribute("hotTagList", tagService.list(new QueryWrapper<Tag>().lambda().eq(Tag::getHot, true).last("limit 10")));
    }
}